import {number, isNumber} from './number.js'
import {css} from './css.js'

const T = true
const F = false
const N = null
const doc = document
const cvs = document.documentElement

const _arr_comma = a => a.split(',')

const _snaptype = {
	h : _arr_comma('21,12,34,43'),
	v : _arr_comma('41,14,32,23'),
	a : _arr_comma('41,32,14,23,21,34,12,43,11'),
	t: ['tt'], b: ['bb'], l: ['ll'], r: ['rr'], c: ['cc'], top: ['tt'], bottom: ['bb'], left: ['ll'], right: ['rr'],
	tl: ['11'], tr: ['22'], rt: ['22'], rb: ['33'], br: ['33'], bl: ['44'], lb: ['44'], lt: ['11'], 
	'1': ['11'], '2': ['22'], '3': ['22'], '4': ['33'], '5': ['33'], '6': ['44'], '7': ['44'], '8': ['11']
}

const _snapMag = (function() {
	var r = [23,32,12,43,22,33,'rr','lr'], b = [14,23,34,43,33,44,'bb','tb'], i, o = {pix: {r:{}, b:{}}, mag: {l:{}, r:{}, t:{}, b:{}}, inner:{}};
	i = r.length; while (i --) o.pix.r[r[i]] = T;
	i = b.length; while (i --) o.pix.b[b[i]] = T;
	var r = [21,34,22,33,'rr','rl'], b = [41,32,44,33,'bt','bb'], l = [12,43,11,44,'lr','ll'], t = [14,23,11,22,'tb','tt'];
	i = r.length; while (i --) o.mag.r[r[i]] = T;
	i = b.length; while (i --) o.mag.b[b[i]] = T;
	i = l.length; while (i --) o.mag.l[l[i]] = T;
	i = t.length; while (i --) o.mag.t[t[i]] = T;
	var r = [11,22,33,44,'tt','bb','ll','rr'];
	i = r.length; while (i --) o.inner[r[i]] = T;
	return o;
})()

const canvasOffset = function(o) {
	var a = bcr(o);
	a.right  = cvs.clientWidth - a.right;
	a.bottom = cvs.clientHeight - a.bottom;
	return a;
}

const offset = function(a, b) {
	let r = {top: 0, left: 0, width: a.offsetWidth, height: a.offsetHeight}
	do {
		r.top += a.offsetTop
    r.left += a.offsetLeft
	} while((a = a.offsetParent) && b != a)
	return r
}

const bcr = function(a) {
	var b = cvs.clientLeft, c = cvs.scrollLeft, d = cvs.clientTop, e = cvs.scrollTop, o = a && a != doc && (a.isWidget ? a.el() : a), r = o && o.getBoundingClientRect();
	return r ? {left : r.left - b + c, top : r.top - d + e, right : r.right - b + c, bottom : r.bottom - d + e, width : r.width, height : r.height} :
		a == document ? {left: c, top: e, right: cvs.clientWidth + c, bottom: cvs.clientHeight + e, width: cvs.clientWidth, height: cvs.clientHeight} : N;
}

// 获取对齐吸附模式的位置参数。元素四个角，左上为1，右上为2，右下为3，左下为4。目标元素在前，浮动元素在后。如"41"代表目标元素的左下角和浮动元素的左上角粘合。
// @ a -> width, b -> height, c -> toObj offset, d -> adsorb type, e - > fit?[是否自动选择位置，让可见区域最大化], f -> indent[缩进多少像素], u -> range?[浮动元素的限定范围元素]
const snap = function(a, b, c, d, e, f, u) {
	if (!c)
		c = bcr(doc);
	else if (c.nodeType)
		c = bcr(c);
	else if (c.isWidget)
		c = bcr(c.el());
	else if (c.originalEvent || c.clientX != N) {
		c = c.originalEvent || c;
		c = {left: c.clientX, right: c.clientX, top: c.clientY, bottom: c.clientY};
	}
	var t = [], l = [], g, h, k = -1, f = number(f), ew = cvs.clientWidth, eh = cvs.clientHeight,
		s = d ? (_snaptype[d] || ('' + d).split(',')) : _snaptype.a;
	if (/[1-4]/.test(s[0])) {// 1-4是边角对齐 .
		for (var i = 0, o, p, m, n = 0; i < s.length; i ++) {
			g = + s[i].charAt(0), h = + s[i].charAt(1);
			t.push((g === 1 || g === 2 ? c.top : c.bottom) - (h === 3 || h === 4 ? b : 0));
			l.push((g === 1 || g === 4 ? c.left : c.right) - (h === 2 || h === 3 ? a : 0));
			o = t[i] >= 0 && t[i] + b <= eh;
			p = l[i] + a <= ew && l[i] >= 0;
			if (o && p) {
				k = i;
				break;
			} else {
				// 计算可见面积，取最大的那个
				var ot = t[i] < 0 ? -t[i] : 0,
					or = l[i] + a > ew ? l[i] + a - ew : 0,
					ob = t[i] + b > eh ? t[i] + b - eh : 0,
					ol = l[i] < 0 ? -l[i] : 0;
				m = s[i] === '14' || s[i] === '34' ? (a-or)*(b-ot) : s[i] === '23' || s[i] === '43' ? (a-ol)*(b-ot) :
					s[i] === '32' || s[i] === '12' ? (a-ol)*(b-ob) : (a-or)*(b-ob);
				if (!n || n < m) {
					n = m;
					k = i;
				}
			}
		}
	} else {// t r b l 是边线中点对齐 .
		for (var i = 0, o, p, m, n = 0; i < s.length; i ++) {
			g = s[i].charAt(0), h = s[i].charAt(1);
			t.push((g === 'r' || g === 'l' || g === 'c' ? (c.top + c.bottom) / 2 : (g === 't' ? c.top : c.bottom)) - (h === 'r' || h === 'l' || h === 'c' ? b / 2 : (h === 'b' ? b : 0)));
			l.push((g === 't' || g === 'b' || g === 'c' ? (c.left + c.right) / 2 : (g === 'r' ? c.right : c.left)) - (h === 't' || h === 'b' || h === 'c' ? a / 2 : (h === 'r' ? a : 0)));
			o = t[i] >= 0 && t[i] + b <= eh;
			p = l[i] + a <= ew && l[i] >= 0;
			if (o && p) {
				k = i;
				break;
			} else if (o || p) {
				if (d) {
					m = d == _snaptype.v ? (g == 1 || g == 2 ? - t[i] : t[i] + b - eh) : (g == 1 || g == 4 ? - l[i] : l[i] + a - ew);
					if (!n || n > m) {
						n = m;
						k = i;
					}
				} else if (k < 0)
					k = i;
			}
		}
	}  
	if (k < 0) k = 0;
	var y = s[k], o = {left : l[k], top : t[k], bottom: eh - (t[k] + b), right: ew - (l[k] + a), type : y};
	_snapMag.pix.r[y] && (o.pix_r = T);
	_snapMag.pix.b[y] && (o.pix_b = T);
	_snapMag.mag.r[y] && (o.mag_r = T, o.mag = 'r');
	_snapMag.mag.b[y] && (o.mag_b = T, o.mag = 'b');
	_snapMag.mag.l[y] && (o.mag_l = T, o.mag = 'l');
	_snapMag.mag.t[y] && (o.mag_t = T, o.mag = 't');
	_snapMag.inner[y] && (o.inner = T);
	if (f && o.mag) {
		if (o.inner) {
			o.mag_t ? (o.top -= f) : o.mag_b ? (o.bottom -= f) : o.mag_r ? (o.right -= f) : (o.left -= f);
		} else {
			o.mag_t ? (o.bottom -= f) : o.mag_b ? (o.top -= f) : o.mag_r ? (o.left -= f) : (o.right -= f);
		}
	}
	if (e) {// 自适应位置  
		var l = o.left, r = o.right, b = o.bottom, t = o.top;
		if (o.mag_t || o.mag_b) {
			if (o.pix_r)
				r = Math.max(0, l < 0 ? r + l : r), l += o.right - r;
			else
				l = Math.max(0, r < 0 ? r + l : l), r += o.left - l;
		}
		if (o.mag_l || o.mag_r) {
			if (o.pix_b)
				b = Math.max(0, t < 0 ? b + t : b), t += o.bottom - b;
			else
				t = Math.max(0, b < 0 ? b + t : t), b += o.top - t;
		}
		o.left = l, o.right = r, o.top = t, o.bottom = b;
	} 
	if (d === 'cc' && o.top < 0)
		o.top = 0;
	if (u) {
 		var s = canvasOffset(u);
		o.top -= (s.top);
		o.left -= (s.left);
		o.right -= (s.right);
		o.bottom -= (s.bottom);
	}
	o.width  = a;
	o.height = b;
	o.target = c;  
	return o;
}

// @a -> el, b -> snap option
const snapTo = function(a, b) {
	var e = b.type;
	if (e) {
		if (b.pix_r) {
			a.style.right = b.right + 'px';
			a.style.left  = '';
		} else {
			a.style.left  = b.left + 'px';
			a.style.right = '';
		}
		if (b.pix_b) {
			a.style.bottom = b.bottom + 'px';
			a.style.top = '';
		} else {
			a.style.top = b.top + 'px';
			a.style.bottom = '';
		}
	} else
		css(a, b)
}

export {bcr, offset, snap, snapTo}
